package game;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.awt.event.MouseListener ;
import java.awt.event.MouseEvent ;
import java.awt.event.InputEvent ;
import java.awt.image.MemoryImageSource;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.Timer;

public class Rev_Centipede extends Game {
    /** The amount of money in the small stack. */
    double smallStack;
	
    /** The amount of money in the large stack. */
    double largeStack;

    /** The amount the stacks grow each turn. */
    double increment;

	/** Amount of time the player has to make a move, in seconds. */
	final int TURN_TIME = 60;

	/** The amount of time the subject spent thinking about their decision. */
	int playerThinkTime = 0;

    double money_won;
    boolean p1_accepted = false;
    int max_allowed_counts;
    int state = 2 ;
    int count = 0, disable=0, go=0;
    Random generator = new Random();
    int totalTime=TURN_TIME,secs = TURN_TIME, timeTaken=0, thinkSecs=0;
    Timer time = new Timer(1000, new TimeListener());
    Timer thinkTime = new Timer(1000, new ThinkTimeListener());
    Vector<String> totalTimeTaken = new Vector<String>();
    Vector<String> totalThinkTime = new Vector<String>();

	// Game log constants.
	final int GL_ACTION_PASS = 1;
	final int GL_ACTION_HOLD = 2;

    /** Creates new form RevCentipede */
    public Rev_Centipede (String params, int currentRep) {
        super();
//        super("",
//              false, //resizable
//              false, //closable
//              false, //maximizable
//              false);//iconifiable
//        javax.swing.plaf.InternalFrameUI ui = this.getUI();
//        ((javax.swing.plaf.basic.BasicInternalFrameUI)ui).setNorthPane(null);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

		String paramPart[] = params.split(",");
        largeStack = Double.parseDouble(paramPart[2]);
        smallStack = Double.parseDouble(paramPart[3]);
        increment = Double.parseDouble(paramPart[4]);
        max_allowed_counts = Integer.parseInt(paramPart[5]);
		this.params = params;
		repTot = Integer.parseInt (paramPart[1]);
		repNum = currentRep;

        initComponents();
        setLocation(screenSize.width/2-400, screenSize.height/2-300);

        this.setVisible(true);
        runner.addMouseListener( new Rev_Centipede.CheckMouse() ) ;
            addMouseListener( new Rev_Centipede.CheckMouse() ) ;
		this.getGlassPane().addMouseListener(new Rev_Centipede.CheckMouse());

        lblStop.setVisible(false);
        lblPass.setVisible(false);

        updateTimeLabel();
        stackLabel.setVisible (false);

        thinkSecs = generator.nextInt(3) + 5;
        totalThinkTime.add("" + thinkSecs);
        thinkTime.start();

        hideMouse();
    }

    
    public Rev_Centipede() {
        super();
//        super("",
//              false, //resizable
//              false, //closable
//              false, //maximizable
//              false);//iconifiable
//        javax.swing.plaf.InternalFrameUI ui = this.getUI();
//        ((javax.swing.plaf.basic.BasicInternalFrameUI)ui).setNorthPane(null);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        largeStack = 3;
        smallStack = 1;
        increment = 0.25;
        max_allowed_counts = 10;

        initComponents();
        this.setVisible(true);
        setLocation(screenSize.width/2-400, screenSize.height/2-300);

        runner.addMouseListener( new Rev_Centipede.CheckMouse() ) ;
        addMouseListener( new Rev_Centipede.CheckMouse() ) ;

        lblStop.setVisible(false);
        lblPass.setVisible(false);
        
        updateTimeLabel();

        thinkSecs = generator.nextInt(3) + 5;
        totalThinkTime.add("" + thinkSecs);
        thinkTime.start();

        hideMouse();
    }

    public void calculateResult(){
        secs = TURN_TIME;
		updateTimeLabel();
        generator = new Random();
        double prob_of_passing = 0 ;
        prob_of_passing = generator.nextDouble();

		ArrayList<ArrayList<String>> p2data
				= readCSVFile ("data/Centipede-Player2_data.csv");
		for (int row=1; row<p2data.size(); row++) {
			double p1Money = Double.parseDouble(p2data.get(row).get(0));
			double p1Prob = Double.parseDouble(p2data.get(row).get(1));

			// In case we reach the end of the data file without finding
			// a matching stack size and probability, we set default values.
			if (row == p2data.size()-1 && p1Money < largeStack) {
				p1Money = largeStack;
				p1Prob = 0.5;
			}

			//System.err.println ("[DEBUG]: p1Money=" + p1Money
			//		+ ", largeStack=" + largeStack);
			if (p1Money >= largeStack) {
				//System.err.println ("[DEBUG]: prob_of_passing="
				//		+ prob_of_passing + ", p1Prob=" + p1Prob);
				if (prob_of_passing < p1Prob) {
					state = 1;
					largeStack += increment;
					smallStack += increment;
					//System.err.println("[DEBUG]: P1 passed." );
					S1();
					break;
				}
				else {
					state = 3 ;  // Game ending state
					money_won = smallStack;
					p1_accepted = true;

					writeGameLog (playerId + ",2," + playerThinkTime + ","
						+ GL_ACTION_HOLD + ",");
					playerThinkTime = 0;

					//System.err.println("[DEBUG]: P1 accepted." );
					S3() ;
					break ;
				}
			}
		}
    }

    private void hideMouse() {
        int[] pixels = new int[16 * 16];
        Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
        Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisibleCursor");
        this.getGlassPane().setCursor(transparentCursor);
		this.getGlassPane().setVisible(true);
        runner.setCursor(transparentCursor);
    }

    public void S1(){
        System.out.println("in S1()") ;
        stackLabel.setText("Large stack: "+ String.format ("$%.2f", largeStack)
                + ", Small stack: " + String.format ("$%.2f", smallStack)) ;
        stackLabel.setVisible (true);
        l5.setText( "What would you like to do?");

    }
    public void S2(){
        System.out.println("in S2()") ;
        stackLabel.setText(null);
        l6.setText(null);
        lblStop.setVisible(false);
        lblPass.setVisible(false);
        l5.setText("Waiting for Player 1...");
		l5.setVisible(true);
    }
    public void S3(){
        System.out.println("in S3()") ;
        lblStop.setVisible(false);
        lblPass.setVisible(false);
        stackLabel.setText(null);

        if (count >= max_allowed_counts) {
            l5.setText("Maximum number of passes reached.") ;
            totalTimeTaken.add("MaxLimit");
        }
		else if (p1_accepted == true) {
            l5.setText("Player 1 stopped the game.");
            totalThinkTime.add("Stop");
        }
		else {
            l5.setText("You stopped the game.");
            timeTaken = totalTime - secs;
            totalTimeTaken.add(timeTaken+"s");
            totalTimeTaken.add("Stop");
        }
		l5.setVisible (true);

        secs=0;
        stackLabel.setText("");
        lblStop.setVisible(false);
        lblPass.setVisible(false);
    }

	/**
	 * Updates the time label at the top.
	 */
	private void updateTimeLabel() {
		int min = secs/60;
		int sec = secs%60;
		lblTime.setText(min+":"+((sec<10)?"0":"")+sec);
	}

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        l2 = new javax.swing.JLabel();
        l3 = new javax.swing.JLabel();
        l5 = new javax.swing.JLabel();
        l6 = new javax.swing.JLabel();
        lblStop = new javax.swing.JLabel();
        lblPass = new javax.swing.JLabel();
        lblTime = new javax.swing.JLabel();
        stackLabel = new javax.swing.JLabel();

        setBackground(new java.awt.Color(255, 255, 255));
        setBorder(null);
        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setMaximumSize(new java.awt.Dimension(800, 600));
        setMinimumSize(new java.awt.Dimension(800, 600));
        setPreferredSize(new java.awt.Dimension(800, 600));

        l2.setFont(new java.awt.Font("Calibri", 1, 28));
        l2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        l2.setText("You are player 2");

        l3.setFont(new java.awt.Font("Calibri", 1, 28));

        l5.setFont(new java.awt.Font("Calibri", 1, 28));
        l5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        l5.setText("Waiting for Player 1 ...");

        l6.setFont(new java.awt.Font("Calibri", 1, 28));
        l6.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);

        lblStop.setFont(new java.awt.Font("Calibri", 1, 24));
        lblStop.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblStop.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/redStop.png"))); // NOI18N

        lblPass.setFont(new java.awt.Font("Calibri", 1, 24));
        lblPass.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblPass.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/greenPass.png"))); // NOI18N

        lblTime.setFont(new java.awt.Font("Calibri", 1, 36));
        lblTime.setForeground(new java.awt.Color(153, 102, 0));
        lblTime.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/hrGlass.png"))); // NOI18N
        lblTime.setText("3:00");

        stackLabel.setFont(new java.awt.Font("Calibri", 1, 32));
        stackLabel.setForeground(new java.awt.Color(0, 51, 255));
        stackLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        stackLabel.setText("You have $");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(l6, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(lblStop, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 233, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(62, 62, 62)
                .add(lblPass)
                .add(124, 124, 124))
            .add(layout.createSequentialGroup()
                .add(lblTime, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 796, Short.MAX_VALUE)
                .add(4, 4, 4))
            .add(layout.createSequentialGroup()
                .add(285, 285, 285)
                .add(l3)
                .addContainerGap(515, Short.MAX_VALUE))
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(l5, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                    .add(l2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE))
                .addContainerGap())
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .add(stackLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(lblTime)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(l2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 59, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(18, 18, 18)
                .add(l3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 51, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(stackLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 70, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(l5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 81, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(18, 18, 18)
                        .add(l6, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 94, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(139, 139, 139))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 108, Short.MAX_VALUE)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                            .add(lblPass, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .add(lblStop))
                        .add(68, 68, 68))))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    @Override
    public synchronized void addMouseListener(MouseListener l) {
        super.addMouseListener(l);
    }

    class CheckMouse implements MouseListener{
         public void mousePressed(MouseEvent e) { hideMouse(); }
         public void mouseReleased(MouseEvent e) {}
         public void mouseEntered(MouseEvent e) {}
         public void mouseExited(MouseEvent e) {}
        
        public void mouseClicked(MouseEvent e) {
            int modifiers = e.getModifiers();
            if ((modifiers & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
                if ( state == 3 ){
//                    setVisible(false);
//                    G.free = true;
                }
                if (state == 1) {
                    if( count < max_allowed_counts){
                        state = 2 ;
                        S2();

						writeGameLog (playerId + ",2," + playerThinkTime + ","
							+ GL_ACTION_PASS + "," + GL_ACTION_PASS);
						playerThinkTime = 0;

                        largeStack += increment;
                        smallStack += increment;

                        thinkSecs = generator.nextInt(3) + 5;
                        totalThinkTime.add(thinkSecs+"s");
                        timeTaken = totalTime - secs;
                        totalTimeTaken.add(timeTaken+"s");

						time.stop();
                        thinkTime.start();
                    }
                    else{
                        //state = 3;
                        //S3() ;
                    }
                }
            }
            if ((modifiers & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {}
            if ((modifiers & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
				if( state == 3 ){}
                if( state == 1 ){
                    // System.err.println ("P2 gets large stack " + largeStack);
                    money_won = largeStack;
					writeGameLog (playerId + ",2," + playerThinkTime + ","
						+ GL_ACTION_PASS + "," + GL_ACTION_HOLD);
					playerThinkTime = 0;
                    state = 3 ;
                    S3() ;
                }
            }
        }
    }

    class TimeListener implements ActionListener {
    	
        public void actionPerformed(ActionEvent e) {
    		secs--;
			playerThinkTime++;
            if(secs>=0) {
                updateTimeLabel();
            }
            if(secs==0) {
                //time.stop();

                state = 3;
                lblStop.setVisible(false);
                lblPass.setVisible(false);
                l2.setText("Sorry, your time is up.");
				writeLog (playerId + ",2,\"" + params + "\"," + repNum
					+ "," + repTot + ",TimeOut,TimeOut");
                totalTimeTaken.add("TimeOut");
            }
            if(secs==-6) {
                time.stop();
                try{
					totalMoneyWon += money_won;
                    System.out.println("money_Won: " + money_won) ;

					double oppMoney = (money_won == largeStack ? smallStack
						: largeStack);
					writeLog (playerId + ",2,\"" + params + "\"," + repNum
						+ "," + repTot + ","
						+ String.format ("$%.2f", money_won) + ","
						+ String.format ("$%.2f", oppMoney));
                }catch(Exception ex){
                    ex.printStackTrace();
                    logError(ex);
                }
                state = 4;
                setVisible(false);
                free=true;
            }
    	}

    }

	// Timer for player 1's thinking time, even though there is no player 1.
    class ThinkTimeListener implements ActionListener {
    	
        public void actionPerformed(ActionEvent e) {
    		thinkSecs--;
            if(thinkSecs==0) {
                thinkTime.stop();
                stackLabel.setText("Large stack: "
					+ String.format ("$%.2f", largeStack) + ", Small stack: "
					+ String.format ("$%.2f", smallStack));
                stackLabel.setVisible (true);
                l5.setVisible (false);
                lblStop.setVisible(true);
                lblPass.setVisible(true);
                calculateResult();
                time.start();
            }
    	}
    }


    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    JFrame main = new JFrame();
                    JDesktopPane dPane = new JDesktopPane();
                    Rev_Centipede frame = new Rev_Centipede();
                    main.setSize(820, 620);
                    dPane.add(frame);
                    main.add(dPane);
                    main.setVisible(true);
                    dPane.setVisible(true);
                    frame.setSelected(true);
                    frame.setVisible(true);
                } catch(Exception ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel l2;
    private javax.swing.JLabel l3;
    private javax.swing.JLabel l5;
    private javax.swing.JLabel l6;
    private javax.swing.JLabel lblPass;
    private javax.swing.JLabel lblStop;
    private javax.swing.JLabel lblTime;
    private javax.swing.JLabel stackLabel;
    // End of variables declaration//GEN-END:variables

}
